//
// Created by wujehy on 2020/8/3.
//

#include "NetWorkWarpper.h"
#include <handy/handy.h>
#include <Network.pb.h>
#include "NetWorkModule/TCPServer.h"
#include "NetWorkModule/HttpServer.h"
#include "NetWorkModule/Client.h"
#include "NetWorkModule/ContextDataType.h"
#include "GeeJoan/NetWorkPackage.pb.h"
#include "GeeJoan/ErrorModule.pb.h"

void NetWorkWarpper::init()
{
    initCallbacks();
    m_businessManager.setNetWorkWarpper( this );
    m_businessManager.init();

    //
    handy::setloglevel( "TRACE" );
    m_eventBase = new handy::MultiBase( this->thread_size );
    initTcpServer();
    initClient();

}

NetWorkWarpper::~NetWorkWarpper()
{
    if (m_eventBase != nullptr)
    {
        delete m_eventBase;
    }

    if (tcpServer)
    {
        delete tcpServer;
    }

    if (httpServer)
    {
        delete httpServer;
    }

    if (client)
    {
        delete client;
    }
}

void NetWorkWarpper::initClient()
{
    if (client == nullptr)
    {
        client = new Client;
    }
    client->sethander( this->m_eventBase );
    client->setNetWorkWarpper( this );
    client->init();
}

void NetWorkWarpper::initTcpServer()
{
    if (tcpServer == nullptr)
    {
        tcpServer = new TCPServer;
    }
    //设置端口
    tcpServer->setServerPort( tcpServerPort );
    tcpServer->sethander( this->m_eventBase );
    tcpServer->setNetWorkWarpper( this );
    tcpServer->init();

}

void NetWorkWarpper::initHttpServer()
{
    if (httpServer == nullptr)
    {
        httpServer = new HttpServer;
    }
    httpServer->sethander( this->m_eventBase );
    httpServer->setNetWorkWarpper( this );
    httpServer->init();
}

void NetWorkWarpper::initCallbacks()
{
    using namespace handy;
    using namespace GeeJoan::Protocol;
    using namespace GeeJoan::Protocol;

    this->onConnectCallback = [&](const TcpConnPtr &con)
    {
        if (con->getState() == TcpConn::Connected)
        {
            // 上下文中存储设备
            con->context<ContextDataType>().client_id = m_client_id;
            info( "current client id %d ", m_client_id );
            m_id_client_map.insert( {m_client_id, con} );
            m_client_id++;

            NetWork::NetWorkPackageRespose respose;
            Error::ErrorMessage errorMessage;
            errorMessage.set_errmsg( "hello" );
            respose.set_taskid( 0 );
            respose.set_code( 200 );
            respose.set_type_m((NetWork::NetWorkPackageModel) 0 );
            respose.set_type_sub( 0 );
            respose.set_body( errorMessage.SerializeAsString());
            con->send( respose.SerializeAsString());
        } else if (con->getState() == TcpConn::Closed)
        {
            // 断开链接 移除设备信息
            m_id_client_map.erase( con->context<ContextDataType>().client_id );
        }
    };
    this->onMessageCallback = [&](const TcpConnPtr &conn, Slice msg)
    {
        using GeeJoan::Protocol::NetWork::NetWorkPackageRequest;
        // 接受到 客户端发上的数据包
        std::string message( msg.data(), msg.size()); // 如果是同步则直接拷贝机异步需要new
//        info("onMessageCallback : %s ", message.c_str());
        NetWorkPackageRequest *netWorkPacket = new NetWorkPackageRequest;

        // 拼包, 成功 则处理 都则释放
        if (netWorkPacket->ParseFromString( message ))
        {
            // 指针由其管理 不需要网络分发器 释放
            m_businessManager.route( conn->context<ContextDataType>().client_id, netWorkPacket );
        } else
        {
            delete netWorkPacket;
        }
    };


}

const handy::MsgCallBack &NetWorkWarpper::getOnMessageCallback() const
{
    return onMessageCallback;
}

void NetWorkWarpper::loop()
{

    m_eventBase->loop();
}

void NetWorkWarpper::stop()
{
    m_eventBase->exit();
}
//std::mutex m_mutex;
//NetWorkWarpper *NetWorkWarpper::Instance()
//{
//
//    m_mutex.lock();
//    if (netWorkWarpper == nullptr)
//    {
//        netWorkWarpper = new NetWorkWarpper;
//    }
//    m_mutex.unlock();
//    return netWorkWarpper;
//}

void NetWorkWarpper::setThreadSize(int threadSize)
{
    thread_size = threadSize;
}

NetWorkWarpper::NetWorkWarpper()
{}

const handy::TcpCallBack &NetWorkWarpper::getOnConnectCallback() const
{
    return onConnectCallback;
}

void NetWorkWarpper::call_init_success()
{
    m_businessManager.init_finished();
}

void NetWorkWarpper::setTcpServerPort(int tcpServerPort)
{
    NetWorkWarpper::tcpServerPort = tcpServerPort;
}


ContextDataType::~ContextDataType()
{
    // 链接的时候 任务id 同时 释放
    using handy::Logger;
    info( "ContextDataType delete  id : %d", client_id );

}